using BrainTechLLC;
using System;
using System.Collections.Generic;
using System.Text;

namespace Mud.EmlenMudMain
{
  public class StringLib
  {
    /// <summary>
    /// Adds color given the player's interface... uses 'span' HTML elements
    /// to do color in the web browser, otherwise ANSI... also converts
    /// \n\r's to <br/>, etc.
    /// </summary>
    /// <param name="interfaceType">the interface type for which to create formatted output</param>
    /// <param name="stringToBeFormatted">The original input string</param>
    /// <param name="fFormatNewlines">If true, then format new lines depending on the client interface used.
    /// Also makes sure that the output string has a trailing line break.</param>
    /// <param name="fAllowDangerousCodes">Allow HTML-interface command codes to pass through without modification</param>
    /// <returns>the client-specific, formatted output string</returns>
    public static string add_color(InterfaceType interfaceType, string stringToBeFormatted, bool fFormatNewlines, bool fAllowDangerousCodes)
    {
      int nSpc = 0;
      int nszLen = stringToBeFormatted.Length; // stringToBeFormatted 
      StringBuilder sb = new StringBuilder(nszLen + 1024);
      StringBuilder sbCodes = new StringBuilder(1024);
      int nStartCode = -1;
      int nSpan = 0;
      int nNewLine = 0;
      Stack<string> savedcodes = new Stack<string>(8);
      if (fFormatNewlines)
      {
        if (interfaceType == InterfaceType.HTML)
        {
          sb.Append("<br/>");
        }
        else
        {
          sb.Append("\n\r");
        }
        nNewLine++;
      }

      for (int i = 0; i < nszLen; i++)
      {
        char c = stringToBeFormatted[i];
        if (interfaceType == InterfaceType.HTML)
        {
          if (c == '\n')
          {
            while (nSpan > 0)
            {
              sb.Append(" </span>");
              nSpan--;
            }

            if (nNewLine < 2)
            {
              sb.Append("<br/>");
            }
            if (savedcodes.Count > 0 && nNewLine == 0)
            {
              string[] rgCodes = savedcodes.ToArray();
              sbCodes.Length = 0;
              for (int mm = 0; mm < rgCodes.Length; mm++)
              {
                string szSpan = rgCodes[mm];
                sbCodes.Insert(0, szSpan);
                nSpan++;
              }
              sb.Append(sbCodes);
            }
            else { savedcodes.Clear(); }
            nNewLine++;
            continue;
          }
          if (c == '\r') continue;
          nNewLine = 0;
          if (c == ' ')
          {
            nSpc++;
            if (nSpc > 2)
            {
              sb.Append("&nbsp;");
            }
            else
            {
              sb.Append(" ");
            }
            continue;
          }
        }

        if (c == '<')
        {
          int nBracket = stringToBeFormatted.IndexOf('>', i);
          if (nBracket > 0)
          {
            int nSuspicious = stringToBeFormatted.IndexOf("script", i, nBracket - i, StringComparison.OrdinalIgnoreCase);
            while (nSuspicious > 0)
            {
              stringToBeFormatted.Remove(nSuspicious + 3, 1);
              nSuspicious = stringToBeFormatted.IndexOf("script", i, nBracket - i, StringComparison.OrdinalIgnoreCase);
            }
          }
        }
        if (c == '{')
        {
          if (interfaceType == InterfaceType.HTML && nSpan > 0)
          {
            sb.Append(" </span>");
            savedcodes.Pop();
            nSpan--;
          }
          nStartCode = i;
        }
        else if (nStartCode >= 0)
        {
          if (interfaceType != InterfaceType.HTML && interfaceType == InterfaceType.ANSI)
          {
            if (c == 'b') { sb.Append('\x1B'); sb.Append("[0;34m"); }
            else if (c == 'B') { sb.Append('\x1B'); sb.Append("[1;34m"); }
            else if (c == 'g') { sb.Append('\x1B'); sb.Append("[0;32m"); }
            else if (c == 'G') { sb.Append('\x1B'); sb.Append("[1;32m"); }
            else if (c == 'c') { sb.Append('\x1B'); sb.Append("[0;36m"); }
            else if (c == 'C') { sb.Append('\x1B'); sb.Append("[1;36m"); }
            else if (c == 'b') { sb.Append('\x1B'); sb.Append("[0;34m"); }
            else if (c == 'w') { sb.Append('\x1B'); sb.Append("[0;37m"); }
            else if (c == 'W') { sb.Append('\x1B'); sb.Append("[1;37m"); }
            else if (char.ToUpper(c) == 'N') { sb.Append('\x1B'); sb.Append("[0;37m"); }
            else if (c == 'p') { sb.Append('\x1B'); sb.Append("[0;35m"); }
            else if (c == 'P') { sb.Append('\x1B'); sb.Append("[1;35m"); }
            else if (c == 'd') { sb.Append('\x1B'); sb.Append("[1;30m"); }
            else if (c == 'r') { sb.Append('\x1B'); sb.Append("[0;31m"); }
            else if (c == 'R') { sb.Append('\x1B'); sb.Append("[1;31m"); }
            else if (c == 'Y') { sb.Append('\x1B'); sb.Append("[0;33m"); }
            else if (c == 'y') { sb.Append('\x1B'); sb.Append("[0;33m"); }
            else if (c == '}') { nStartCode = -1; }
            else if (c == '{') { sb.Append('{'); nStartCode = -1; }
            else { sb.Append("BadBracketCode: " + c.ToString()); nStartCode = -1; }
          }
          else if (interfaceType == InterfaceType.HTML)
          {
            string szColorC = "";
            if (c == 'b') { szColorC = "<span style=\"color: #9999FF;\">"; }
            else if (c == 'B') { szColorC = "<span style=\"color: #CC22FF;\">"; }
            else if (c == 'g') { szColorC = "<span style=\"color: #11AA11;\">"; }
            else if (c == 'G') { szColorC = "<span style=\"color: #22FF22;\">"; }
            else if (c == 'c') { szColorC = "<span style=\"color: #11AAAA;\">"; }
            else if (c == 'C') { szColorC = "<span style=\"color: #22FFFF;\">"; }
            else if (c == 'w') { szColorC = "<span style=\"color: #CCCCCC;\">"; }
            else if (c == 'W') { szColorC = "<span style=\"color: #FFFFFF;\">"; }
            else if (c == 'N') { while (savedcodes.Count > 0) { sb.Append(" </span>"); savedcodes.Pop(); nSpan--; } }
            else if (c == 'n') { if (savedcodes.Count > 0) { sb.Append(" </span>"); savedcodes.Pop(); nSpan--; } }
            //else if (char.ToUpper(c) == 'N') { szColorC = "<span style=\"color: Black;\">"; }
            else if (c == 'p') { szColorC = "<span style=\"color: #CC22EE;\">"; }
            else if (c == 'P') { szColorC = "<span style=\"color: #EE44FF;\">"; }
            else if (c == 'd') { szColorC = "<span style=\"color: #888888;\">"; }
            else if (c == 'r') { szColorC = "<span style=\"color: #AA1111;\">"; }
            else if (c == 'R') { szColorC = "<span style=\"color: #FF9977;\">"; }
            else if (c == 'Y') { szColorC = "<span style=\"color: #FFFF22;\">"; }
            else if (c == 'y') { szColorC = "<span style=\"color: #CCCC11;\">"; }
            else if (c == '#')
            {
              StringBuilder sbCustomColor = new StringBuilder(8);
              sbCustomColor.Append('#');
              while ((i + 2) < nszLen)
              {
                char cN = stringToBeFormatted[i + 1];
                if (char.IsDigit(cN) == true ||
                  (char.ToUpper(cN) >= 'A' && char.ToUpper(cN) <= 'F'))
                {
                  i++;
                  sbCustomColor.Append(cN);
                  if (sbCustomColor.Length == 7)
                  {
                    if (stringToBeFormatted[i + 1] == '}') { i++; nStartCode = -1; }
                    break;
                  }
                }
                else
                {
                  sbCustomColor.Length = 0;
                  break;
                }
              }
              if (sbCustomColor.Length == 7)
              {
                szColorC = "<span style=\"color: " + sbCustomColor.ToString() + ";\">";
              }
              else
              {
                szColorC = "";
              }
            }
            else if (c == '}') { nStartCode = -1; }
            else if (c == '{') { sb.Append('{'); nStartCode = -1; }
            else { sb.Append("BadBracketCode: " + c.ToString()); nStartCode = -1; }

            if (szColorC != "")
            {
              nSpan++;
              sb.Append(szColorC);
              savedcodes.Push(szColorC);
            }
          }
          else
          {
            if (c == '}') { nStartCode = -1; }	// we ignored the {}
            else if (c == '{') { sb.Append('{'); nStartCode = -1; }
            // Do nothing if we don't have ANSI
          }
        }  // nStartCode >= 0  (bracket encountered)
        else
        {	// no braket encountered, simply copy the character
          nSpc = 0;
          sb.Append(c);
        }
      }

      while (nSpan > 0)
      {
        sb.Append(" </span>");
        nSpan--;
      }

      if (nNewLine == 0 && fFormatNewlines == true)
      {
        if ((interfaceType & InterfaceType.HTML) != 0)
          sb.Append("<br/>");
        else
          sb.Append("\n\r");
      }

      if (!fAllowDangerousCodes)
      {
        sb.Replace('|', '!');
      }

      return sb.ToString();
    }

    public static string add_color(InterfaceType ift, string szOrig, bool fFormatNewlines)
    {
      return add_color(ift, szOrig, fFormatNewlines, false);
    }
  }
}
